let _Vue = null

export default class VueRouter {
  static install (Vue) {
    //* 1. 判断当前插件是否已经被安装
    if (VueRouter.install.installed) {
      return
    }

    VueRouter.install.installed = true

    //* 2. 把Vue构造函数记录到全局变量
    _Vue = Vue

    //* 3. 把创建Vue实例时传入的router对象注入到Vue实例中
    //* 需要使用mixin混入
    // _Vue.prototype.$router = this.$options.router 直接这样实现是不行的
    // 因为this指向的是VueRouter(install是静态函数)，并不是Vue的一个实例
    _Vue.mixin({
      beforeCreate () {
        // 混入后所有Vue实例包括组件都会有beforeCreate，导致会运行很多次
        // 所以我们需要判断，只对Vue实例执行，组件不需要执行
        if (this.$options.router) {
          // 组件选项中没有router，注意router是初始化Vue的时候作为参数传入的，就是一个VueRouter实例
          _Vue.prototype.$router = this.$options.router
          this.$options.router.init()
        }
      }
    })
  }

  constructor (options) {
    this.options = options
    this.routeMap = {}
    this.data = _Vue.observable({
      current: '/'
    })
  }

  init () {
    this.createRouteMap()
    this.initComponents(_Vue)
    this.initEvent()
  }

  createRouteMap () {
    //* 建立路由键值对 <路由 - 组件> 储存到routeMap
    this.options.routes.forEach((route) => {
      this.routeMap[route.path] = route.component
    })
  }

  initComponents (Vue) {
    //* 创建routerLink组件
    Vue.component('router-link', {
      props: {
        to: String
      },
      render (h) {
        // 如果不使用完整版本的Vue预编译模板，就需要使用render函数而不是template
        return h(
          'a', // 标签名
          {
            attrs: {
              // html属性
              href: this.to
            }
          },
          [ this.$slots.default ] // 生成的内容
        )
      }
    })

    //* 创建routerView组件
    // render函数不是箭头函数，this会发生改变，要先记住this
    const self = this
    Vue.component('router-view', {
      render (h) {
        const component = self.routeMap[self.data.current]
        return h(component)
      }
    })
  }

  initEvent () {
    // 监听hash变化
    window.addEventListener('hashchange', () => {
      let path = location.hash.slice(1) || '/'
      console.log(path)
      this.data.current = path
    })
  }
}
